1 Introduction

1.1 Latar Belakang

Industri perikanan kepiting memiliki tantangan dalam mengelola populasi dan memastikan produksi yang berkelanjutan. Salah satu aspek penting dalam manajemen populasi adalah pemahaman tentang pertumbuhan dan perkembangan kepiting, termasuk pemantauan usia kepiting yang dibiakkan.

Pemantauan usia kepiting merupakan langkah penting dalam pengelolaan populasi karena membantu dalam menentukan waktu panen yang optimal, memperkirakan ukuran kepiting yang layak untuk dijual, serta memahami pola pertumbuhan populasi. Namun, proses ini seringkali memerlukan biaya dan waktu yang signifikan, terutama jika dilakukan secara manual oleh tenaga kerja manusia.

Untuk meningkatkan efisiensi biaya dan waktu dalam pengembangbiakan kepiting, analisis regresi dapat menjadi alat yang efektif. Analisis regresi memungkinkan kita untuk memahami hubungan antara berbagai variabel dimensi dan volume kepiting terhadap usia kepiting. Dengan memahami hubungan ini, kita dapat membangun model prediktif yang dapat digunakan untuk memperkirakan usia kepiting dan mengetahui variabel apa saja yang berpengaruh dalam menentukan usia kepiting.

Dengan menggunakan analisis regresi untuk memprediksi usia kepiting, pengembangbiakan kepiting dapat menghemat biaya dan waktu yang diperlukan untuk pemantauan manual usia. Selain itu, prediksi usia kepiting yang akurat juga dapat meningkatkan efisiensi operasional, memungkinkan petani untuk mengoptimalkan jadwal panen dan manajemen populasi secara keseluruhan.

Dengan menerapkan pendekatan ini, diharapkan bahwa industri pengembangbiakan kepiting dapat mencapai efisiensi yang lebih tinggi dalam manajemen populasi, serta mengurangi biaya dan waktu yang terlibat dalam pemantauan usia kepiting. Ini akan mendukung pertumbuhan yang berkelanjutan dalam industri perikanan kepiting sambil memastikan pengelolaan yang bertanggung jawab terhadap sumber daya laut.


1.2 Tentang Data

Dataset ini diperoleh melalui kaggle Crab Age Prediction yang diposting oleh GURSEWAK SINGH SIDHU. Dataset ini berisi informasi pengukuran kepiting, dengan informasi kolom sebagai berikut:

Deskripsi data crab:

  • Sex : Jenis kelamin kepiting
    • F (female) : Betina
    • M (male) : Jantan
    • I (Indeterminate): tak tentu
  • Length : Panjang cangkang kepiting (foot)
  • Diameter : Lebar cangkang kepiting (foot)
  • Height : Tebal cangkang kepiting (foot)
  • Weight : Berat kepiting (ons)
  • Shucked.Weight : Berat kepiting tanpa cangkang (ons)
  • Viscera.Weight : Berat jeroan kepiting (ons)
  • Shell.Weight : Berat cangkang kepiting (ons)
  • Age : Usia kepiting (month)

panduan ukuran:

  • 1 foot = 30.48 cm
  • 1 ons = 28,35 gram

2 Analysis Preparation

2.1 Load Packages

Pada artikel ini akan dilakukan pemodelan regresi menggunakan bahasa pemrograman R, berikut adalah beberapa packages yang akan digunakan dalam pemodelan kali ini.

#Package untuk pemrosesan dataframe dan EDA
library(dplyr) 
library(tidyr)
library(corrplot)
library(class)

#Package untuk pengujian asumsi 
library(car)     
library(lmtest)

#Package untuk melakukan evaluasi model
library(caret)
library(MLmetrics)
library(performance)

#Package untuk melakukan visualisasi
library(ggplot2)
library(plotly)
library(glue)
library(GGally)

2.2 Data Preparation

Sebelum dilakukan analisis data lebih lanjut, perlu dilakukan persiapan terlebih dahulu yakni:

  1. Read data set
  2. Pemeriksaan & penyesuaian tipe data

2.2.1 Load Data Set

Untuk load data kedalam R kita gunakan fungsi read.csv untuk membaca dataCrabAgePrediction.csv

crab <- read.csv("data_input/CrabAgePrediction.csv") 
head(crab)

2.2.2 Data Type Checking & Adjustment

Sebelum dilakukan analisis, perlu diperiksa terlebih dahulu apakah tipe data setiap kolom variabel sudah sesuai.

# Pemeriksaan tipe data
glimpse(crab)
#> Rows: 3,893
#> Columns: 9
#> $ Sex            <chr> "F", "M", "I", "F", "I", "F", "F", "M", "I", "I", "M", …
#> $ Length         <dbl> 1.4375, 0.8875, 1.0375, 1.1750, 0.8875, 1.5500, 1.3000,…
#> $ Diameter       <dbl> 1.1750, 0.6500, 0.7750, 0.8875, 0.6625, 1.1625, 1.0000,…
#> $ Height         <dbl> 0.4125, 0.2125, 0.2500, 0.2500, 0.2125, 0.3500, 0.3250,…
#> $ Weight         <dbl> 24.635715, 5.400580, 7.952035, 13.480187, 6.903103, 28.…
#> $ Shucked.Weight <dbl> 12.332033, 2.296310, 3.231843, 4.748541, 3.458639, 13.5…
#> $ Viscera.Weight <dbl> 5.5848515, 1.3749507, 1.6017467, 2.2821347, 1.4883488, …
#> $ Shell.Weight   <dbl> 6.7471810, 1.5592225, 2.7640763, 5.2446575, 1.7009700, …
#> $ Age            <int> 9, 6, 6, 10, 6, 8, 15, 10, 13, 7, 6, 10, 9, 10, 11, 12,…

💡 Hasil pemeriksaan tipe data:

  • data terdiri dari 3.893 observasi
  • terdapat 9 kolom variabel karakteristik kepiting
  • untuk kolom Sex perlu dilakukan penyesuaian menjadi tipe factor
# Penyesuaian Tipe data
crab <- crab %>% mutate(Sex = factor(Sex, levels = c("I","F","M")))
glimpse(crab)
#> Rows: 3,893
#> Columns: 9
#> $ Sex            <fct> F, M, I, F, I, F, F, M, I, I, M, F, M, I, I, F, M, I, M…
#> $ Length         <dbl> 1.4375, 0.8875, 1.0375, 1.1750, 0.8875, 1.5500, 1.3000,…
#> $ Diameter       <dbl> 1.1750, 0.6500, 0.7750, 0.8875, 0.6625, 1.1625, 1.0000,…
#> $ Height         <dbl> 0.4125, 0.2125, 0.2500, 0.2500, 0.2125, 0.3500, 0.3250,…
#> $ Weight         <dbl> 24.635715, 5.400580, 7.952035, 13.480187, 6.903103, 28.…
#> $ Shucked.Weight <dbl> 12.332033, 2.296310, 3.231843, 4.748541, 3.458639, 13.5…
#> $ Viscera.Weight <dbl> 5.5848515, 1.3749507, 1.6017467, 2.2821347, 1.4883488, …
#> $ Shell.Weight   <dbl> 6.7471810, 1.5592225, 2.7640763, 5.2446575, 1.7009700, …
#> $ Age            <int> 9, 6, 6, 10, 6, 8, 15, 10, 13, 7, 6, 10, 9, 10, 11, 12,…

3 Data Analysis

3.1 Exploratory Data Analysis

Setelah kita selesai dengan preparasi data, selanjutnya akan kita lakukan tahapan eksplorasi data dengan tujuan untuk mendapatkan gambaran dari data yang kita miliki. Tahapan yang akan kita lakukan dalam eksplorasi kali ini antara lain:

  1. Pemeriksaan dan penanganan missing value
  2. Ringkasan data
  3. Sebaran data
  4. Korelasi antar variabel

3.1.1 Missing value Checking

Pemeriksaan missing value dilakukan dengan tujuan untuk mengetahui apakah ada informasi kolom dari data yang tidak lengkap, sehinga apabila ditemukan kondisi data yang tidak lengkap dapat dilakukan penanganan sebelum dilkukan analisa lanjutan. untuk melakukannya dapat kita gunakan gabungan fungsi colSums() dan is.na().

colSums(is.na(crab))
#>            Sex         Length       Diameter         Height         Weight 
#>              0              0              0              0              0 
#> Shucked.Weight Viscera.Weight   Shell.Weight            Age 
#>              0              0              0              0

Berdasarkan pemeriksaan diatas diketahui bahwa tidak terdapat missing value untuk setiap kolom pada data crab. Sehingga data dapt kita lakukan pengolahan tahap selanjutnya.


3.1.2 Summary of Data

Untuk mengetahui kondisi dari data yang kita miliki, kita bisa melihat secara sekilas dari ringkasan data yang dapat diperoleh menggunakan fungsi summary()

#persebaran data target
summary(crab)
#>  Sex          Length          Diameter          Height           Weight       
#>  I:1233   Min.   :0.1875   Min.   :0.1375   Min.   :0.0000   Min.   : 0.0567  
#>  F:1225   1st Qu.:1.1250   1st Qu.:0.8750   1st Qu.:0.2875   1st Qu.:12.6722  
#>  M:1435   Median :1.3625   Median :1.0625   Median :0.3625   Median :22.7930  
#>           Mean   :1.3113   Mean   :1.0209   Mean   :0.3494   Mean   :23.5673  
#>           3rd Qu.:1.5375   3rd Qu.:1.2000   3rd Qu.:0.4125   3rd Qu.:32.7862  
#>           Max.   :2.0375   Max.   :1.6250   Max.   :2.8250   Max.   :80.1015  
#>  Shucked.Weight     Viscera.Weight      Shell.Weight           Age        
#>  Min.   : 0.02835   Min.   : 0.01418   Min.   : 0.04252   Min.   : 1.000  
#>  1st Qu.: 5.34388   1st Qu.: 2.66485   1st Qu.: 3.71378   1st Qu.: 8.000  
#>  Median : 9.53961   Median : 4.86194   Median : 6.66213   Median :10.000  
#>  Mean   :10.20734   Mean   : 5.13655   Mean   : 6.79584   Mean   : 9.955  
#>  3rd Qu.:14.27397   3rd Qu.: 7.20077   3rd Qu.: 9.35534   3rd Qu.:11.000  
#>  Max.   :42.18406   Max.   :21.54562   Max.   :28.49125   Max.   :29.000

💡 Insight:

Berdasarkan summary diatas dapat kita ketahui bahwa:

  • jumlah data kepiting berjenis kelamin jantan lebih banyak +- 200an data dibandingkan dengan jenis kelmin betina dan yang belum teridentifikasi jenis kelaminnya
  • rata-rata panjang tubuh kepiting adalah 1.3113 kaki atau setara dengan 39,97 cm
  • rata-rata diameter tubuh kepiting adalah 1.0209 kaki atau setara dengan 31.12 cm
  • rata-rata tinggi tubuh kepiting adalah 0.3494 kaki atau setara dengan 10.65 cm
  • rata-rata berat kepiting keseluruhan adalah 23.5673 ons atau setara dengan 668.12 gram
  • rata-rata berat daging kepiting tanpa cangkang adalah 10.20734 ons atau setara dengan 289.37 gram
  • rata-rata berat jeroan kepiting adalah 5.13655 ons atau setara dengan 145.62 gram
  • rata-rata berat cangkang kepiting adalah 6.79584 ons atau setara dengan 192.66 gram

3.1.3 Data Distribution

1. Crab Age

age<-ggplot(data = crab, mapping = aes(y = Age, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Age)), lwd = 0.8, linetype="dotted")+
  labs(title = "Distribution Crab Age by Sex",
       x = "Sex",
       y = "Age") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

ggplotly(age)

💡 Insight:

Berdasarkan hasil visualisasi boxplot usia kepiting berdasarkan jenis kelamin kepiting diatas dapat kita ketahui bahwa kepiting yang belum teridentifikasi jenis kelaminnya adalah kepiting yang berada di rentang usia kurang dari 9 bulan.

2. Crab Dimension

# Crab length
p1 <-ggplot(data = crab, mapping = aes(y = Length, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Length)), lwd = 0.8, linetype="dotted")+
  labs(title = "Distribution Crab Dimension by Sex",
       x = "Sex",
       y = "Length") +
  theme(plot.title = element_text(hjust = 0.5, vjust = 1.1))

# Crab Diameter
p2 <-ggplot(data = crab, mapping = aes(y = Diameter, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Diameter)), lwd = 0.8, linetype="dotted")

#Crab Height
p3 <-ggplot(data = crab, mapping = aes(y = Height, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Height)), lwd = 0.8, linetype="dotted")


fig1 <- subplot(
  ggplotly(p1), 
  ggplotly(p2),
  ggplotly(p3), 
  nrows = 1,
  heights = 0.8) 


annotations = list( 
  list( 
    x = 0.175,  
    y = 0.9,  
    text = "Crab Length",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.5,  
    y = 0.9,  
    text = "Crab Diameter",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.85,  
    y = 0.9,  
    text = "Crab Height",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ))

fig1 %>% layout(annotations = annotations)

💡 Insight:

Berdasarkan hasil visualisasi boxplot diatas dapat kita ketahui bahwa kepiting jantan cenderung memiliki ukuran yang lebih besar dibandingkan kepiting betina, dan terdapat kepiting dengan tinggi badan cukup ekstrim yaitu 2.83 kaki atau setara dengan 86.26 cm, hal tersebut mengindikasikan adanya kesalahan input data dikarenakan sangat kecil kemungkinan ditemukannya kepiting dengan tinggi badan yang hampir mendekati 1 meter.

3. Crab Volume

# Crab Weight
p4 <-ggplot(data = crab, mapping = aes(y = Weight, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Weight)), lwd = 0.8, linetype="dotted")+
  labs(title = "Distribution Crab Volume by Sex",
       x = "Sex",
       y = "Length") +
  theme(plot.title = element_text(hjust = 0.5, vjust = 1.1))

# Crab Shucked.Weight
p5 <-ggplot(data = crab, mapping = aes(y = Shucked.Weight, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Shucked.Weight)), lwd = 0.8, linetype="dotted")

# Crab Viscera.Weight
p6 <-ggplot(data = crab, mapping = aes(y = Viscera.Weight, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Viscera.Weight)), lwd = 0.8, linetype="dotted")

# Crab Shell.Weight
p7 <-ggplot(data = crab, mapping = aes(y = Shell.Weight, x = Sex))+
  geom_boxplot(fill = "black", color = "red")+
  geom_hline(aes(yintercept = mean(Shell.Weight)), lwd = 0.8, linetype="dotted")

fig2 <- subplot(
          ggplotly(p4), 
          ggplotly(p5),
          ggplotly(p6),
          ggplotly(p7),
          nrows = 1,
          heights = 0.8 )

annotations = list( 
  list( 
    x = 0.120,  
    y = 0.9,  
    text = "Crab Weight",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.375,  
    y = 0.9,  
    text = "Crab Shucked.Weight",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.625,  
    y = 0.9,  
    text = "Crab Viscera.Weight",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),
  list( 
    x = 0.885,  
    y = 0.9,  
    text = "Crab Shell.Weight",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ))

fig2 %>% layout(annotations = annotations)

💡 Insight:

Berdasarkan hasil visualisasi boxplot diatas terlihat bahwa dari semua informasi berat yang ada memiliki visual yang sama, hal ini terjadi karea tiga informasi berat daging kepiting tanpa cangkang, berat jeroan kepiting dan berat cangkang bisa terwakili oleh satu informasi utama yakni berat kepiting keseluruhan. Olehkarenanya dalam analisa selanjutnya bisa digunakan berat kepiting secara keseluruhan yang diperoleh dari hasil penimbangan singkat tanpa harus melakukan pembedahan dan pemisahan bagian kepiting. Dan dapat kita ketahui juga apabila kepiting jantan cenderung lebih berat dibandingkan dengan kepiting betina, hal ini bisa terjadi diindikasikan karena biasanya kepiting jantan memiliki ukuran capit yang dapat bertumbuh lebih besar dibandingkan kepiting betina.


3.1.4 Correlation

Korelasi merupakan suatu nilai yang menggambarkan seberapa erat hubungan antara suatu variabel teerhadap variabel lainnya, nilai korelasi yang mendekati 1 menunjukkan korelasi positif kuat dan nilai korelasi yang mendekati -1 menunjukkan korelasi negatif kuat.

Nilai korelasi juga dapat digunakan sebagai salah satu pemeriksaan adanya multikolinieritas antara variabel prediktor, yang dapat dilihat dari hubungan yang kuat antara variabel prediktor.

ggcorr(crab,label = TRUE )

💡 Insight:

Berdasarkan hasil visualisasi corelation plot yang berwarna merah diatas dapat kita ketahui bahwa seluruh variabel dimensi dan volume memiliki korelasi positif terhadap usia. Dan terlihat bahwa terdapat nilai korelasi sempurna sebesar 1, yang ditunjukkan antara variabel volume (berat, berat cangkang, berat jeroan, dan berat kepiting tanpa cangkang). oleh karenanya pada tahapan selanjutnya cukup digunakan satu informasi berat kepiting saja.


3.2 Model Building

3.2.1 Cross-Validation

Tahapan awal yang perlu dilakukan sebelum pembuatan model adalah cross validation dimana tahapan ini akan membagi data menjadi dua bagian, yakni _data train_ dan _data test_. Hal ini bertujuan untuk mengetahui seberapa baik model untuk memprediksi unseen data [data baru yang belum pernah dilihat oleh model], dimana:

  • data train akan digunakan untuk membuat model dengan jumlah proporsi data yang lebih besar dibandingkan dengan data test, sedangkan
  • data test akan digunakan untuk mengevaluasi model yang telah dibuat menggunakan data train

untuk melakukan cross validation, kita dapat menggunakan fungsi sample() yang akan mengambil index dari jumlah data. paramater :

  • x = berisi list / jumlah data populasi
  • size = besaran proporsi data yg akan diambil

index yang diperoleh pada hasil sample akan sangat dimungkinkan berbeda setiap kali kode ini dijalankan dan atau di setiap device. Untuk mengatur agar setiap hasil sample yang dijalankan akan sama maka fungsi sample() ini perlu dijalankan beriringan dengan fungsi set.seed().

Pada analisis kali ini akan digunakan 75% data sebagai data train, dan sisanya 25% data akan digunakan sebagai data test.

RNGkind(sample.kind = "Rounding")
set.seed(417)

# index sampling 
# ---- mengambil 25 persen index dari jumlah data -----
index <- sample(x = nrow(crab),size = round(0.25*nrow(crab))) 

# splitting data 
crab_test  <- crab[index,]  #ambil data 25%
crab_train <- crab[-index,] #ambil data 75%

Dan berikut ini adalah hasil pembagian dataset

# menampilkan jumlah data hasil pembagian
j.data <- data.frame(Data = c("Data Train (75%)","Data Test (25%)","Total Data (100%)"),
                     n = c(nrow(crab_train),nrow(crab_test),nrow(crab)))
j.data

3.2.2 Multicolinierity Checking

Sebelum dilakukan pemodelan, terdapat satu asumsi Regresi yang perlu diuji terlebih dahulu. yakni asumsi multikolinieritas. Multikolinieritas adalah kondisi adanya korelasi antar prediktor yang kuat. Hal ini tidak diinginkan karena menandakan prediktor redundan pada model, yang seharusnya dapat dipilih salah satu saja dari variable yang hubungannya amat kuat tersebut. Harapannya tidak terjadi multikolinieritas

Untuk menguji VIF (Variance Inflation Factor) dapat dilakukan menggunakan fungsi vif() dari package car, dengan ketentuan:

  • nilai VIF > 10: terjadi multikolinieritas pada model
  • nilai VIF < 10: tidak terjadi multikolinieritas pada model
lm(Age ~., crab_train) %>%  # membuat model regresi linier
  vif()                     # memeriksa nilai VIF
#>                      GVIF Df GVIF^(1/(2*Df))
#> Sex              1.514576  2        1.109361
#> Length          37.516962  1        6.125109
#> Diameter        39.356577  1        6.273482
#> Height           6.952946  1        2.636844
#> Weight         105.037871  1       10.248799
#> Shucked.Weight  27.773730  1        5.270079
#> Viscera.Weight  16.689947  1        4.085333
#> Shell.Weight    20.514128  1        4.529252

Berdasarkan hasil pemeriksaan nilai VIF diatas, dapat kita ketahui bahwa:

  1. Tidak terjadi multikolinieritas untuk variabel Sex dan Height
  2. Terjadi multikolinieritas antara variabel Length dengan Diameter, sehingga bisa dipilih salah satu saja untuk digunakan dalam pemodelan.
  3. Terjadi multikolinieritas antara variabel Weight, Shucked.Weight, Viscera.Weight, dan Shell.Weight, sehingga bisa dipilih salah satu saja untuk digunakan dalam pemodelan

Selanjutnya akan dicoba diperiksa nilai VIF untuk model regresi dengan variabel Sex, Height, Length, dan Weight.

lm(Age ~ Sex + Height + Length + Weight , crab_train) %>%  # membuat model regresi linier
  vif()  # memeriksa nilai VIF
#>            GVIF Df GVIF^(1/(2*Df))
#> Sex    1.466308  2        1.100415
#> Height 6.168242  1        2.483595
#> Length 8.782291  1        2.963493
#> Weight 8.075616  1        2.841763

Setelah dikeluarkan beberapa variabel prediktor, kini sudah tidak lagi ditemukan multikolinieritas. Sehingga pada tahapan selanjutnya hanya akan digunakan variable berikut :

  1. Sex
  2. Height
  3. Length
  4. Weight

3.2.3 Model Fitting

Selanjutnya adalah membuat model regresi linier, yang dapat dilakukan menggunakan fungsi lm() dengan parameter:

  • formula : target ~ prediktor
  • data : data yang digunakan

3.2.3.1 Simple Linear Regression

Akan dibuat model regresi linear sederhana (1 variabel prediktor) dengan variabel prediktor Length karena variabel tersebut memiliki korelasi positif tertinggi di antara variabel lainnya terhadap variabel target Age.

model1 <- lm(formula = Age ~ Length, 
                 data = crab_train) 
summary(model1)
#> 
#> Call:
#> lm(formula = Age ~ Length, data = crab_train)
#> 
#> Residuals:
#>     Min      1Q  Median      3Q     Max 
#> -5.9417 -1.6894 -0.7317  0.8686 16.6790 
#> 
#> Coefficients:
#>             Estimate Std. Error t value            Pr(>|t|)    
#> (Intercept)   2.2178     0.2226   9.962 <0.0000000000000002 ***
#> Length        5.8933     0.1653  35.642 <0.0000000000000002 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 2.641 on 2918 degrees of freedom
#> Multiple R-squared:  0.3033, Adjusted R-squared:  0.3031 
#> F-statistic:  1270 on 1 and 2918 DF,  p-value: < 0.00000000000000022

💡 Insight:

Berdasarkan hasil summary model diatas dapat kita ketahui bahwa :

  • Hasil pengujian signifikansi prediktor diperoleh nilai p-value untuk variabel Length sebesar 0.0000000000000002 < 0.05, maka dapat dinyatakan bahwa variabel length signifikan berpengaruh terhadap Usia kepiting.

  • diperoleh nilai adj.R-squared sebesar 0.3031 dengan kata lain hanya sebesar 30.31% dari variabel Length dapat menjelaskan model (pengaruh terhadap Usia Kepiting).

  • walaupun variabel Length signifikan berpengaruh terhadap Usia kepiting, namun nilai adj.R-squared yang diperoleh masih terlalu kecil, sehingga untuk meningkatkan nilai adj.R-squared perlu dilakukan penambahan variabel lainnya.

dan dibawah ini adalah bentuk visualisasi garis regresi yang terbentuk antara variabel Length dan Age

ggplot(data = crab_train, mapping=aes(x = Length, y = Age))+
  geom_point()+
  scale_color_brewer(palette="Accent")+
  geom_smooth(method="lm", se=FALSE)+
  labs(title="Plot Regresi Crab Length vs Crab Age")+
  theme_minimal()


3.2.3.2 Multiple Linear Regression

Untuk meningkatkan performa model akan dibuat model regresi linear berganda (lebih dari 1 variabel prediktor).

  • Variabel target: Age
  • Variabel PRediktor:
    • Sex
    • Height
    • Length
    • Weight
model2 <- lm(formula = Age ~ Sex + Height + Length + Weight, 
                 data = crab_train) 
summary(model2)
#> 
#> Call:
#> lm(formula = Age ~ Sex + Height + Length + Weight, data = crab_train)
#> 
#> Residuals:
#>     Min      1Q  Median      3Q     Max 
#> -6.0775 -1.5807 -0.5166  0.8538 14.9977 
#> 
#> Coefficients:
#>              Estimate Std. Error t value             Pr(>|t|)    
#> (Intercept)  2.573929   0.367400   7.006 0.000000000003037826 ***
#> SexF         1.109700   0.136922   8.105 0.000000000000000771 ***
#> SexM         0.960195   0.128845   7.452 0.000000000000120187 ***
#> Height      18.181021   1.205283  15.084 < 0.0000000000000002 ***
#> Length       0.591763   0.462461   1.280               0.2008    
#> Weight      -0.019679   0.009597  -2.051               0.0404 *  
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 2.493 on 2914 degrees of freedom
#> Multiple R-squared:  0.3803, Adjusted R-squared:  0.3792 
#> F-statistic: 357.6 on 5 and 2914 DF,  p-value: < 0.00000000000000022

💡 Insight:

Berdasarkan hasil summary model diatas dapat kita ketahui bahwa :

  • Dari keseluruhan variabel yang disertakan, kini hanya variabel Length yang tidak signifikan berpengaruh terhadap Usia kepiting.

  • diperoleh nilai adj.R-squared sebesar 0.3792 dengan kata lain hanya sebesar 37.92% dari variabel - variabel dapat menjelaskan model (pengaruh terhadap Usia Kepiting).

  • hasil penambahan variabel prediktor hanya meningkatkan performa model sebesar 0.0761 atau sebesar 7,61%.


3.2.4 Model evaluation

3.2.4.1 Model Performance

Untuk mengetahui apakah model yang sudah dibuat cukup baik dalam memprediksi data baru, dapat dilihat dengan melihat apakah hasil prediksi tersebut sudah menghasilkan error yang paling kecil. Error/residual adalah selisih antara hasil prediksi dengan nilai aktual. Untuk melihat seberapa besar tingkat error dapat dilakukan dengan menggunakan nilai MAPE ( Mean Absolute Percentage Error ) yang didapat dilakukan dengan fungsi MAPE().

pred_train <- model2$fitted.values
pred_test <- predict(model2,crab_test)

Eval <- data.frame(Data = c("Data Train", "Data Test"),
                   MAPE = c(MAPE(pred_train,crab_train$Age)*100, MAPE(pred_test, crab_test$Age)*100))
Eval

💡 Insight:

Berdasarkan hasil evaluasi model2 diatas, diperoleh nilai MAPE untuk data train dan data test kurang dari 20%. Artinya model sudah cukup baik untuk digunakan memprediksi data baru.


3.2.4.2 Regression Assumption Check

Terdapat 4 pengujian asumsi regresi yang harus dilakukan antara lain:

  1. Multikolinearitas
  2. Linearitas
  3. Normalitas
  4. Heteroskedastisitas

1. Linieritas

Linearitas artinya target variabel dengan prediktornya memiliki hubungan yang linear atau hubungannya bersifat garis lurus.

Untuk menentukan asumsi linearity dari sebuah model regresi (multiple linier regreesion) dapat dilakukan dengan membuat plot residual vs fitted values. Plot ini merupakan scatter plot dengan sumbu x adalah fitted values (hasil prediksi variabel target) dan sumbu y adalah nilai residual/error yang dihasilkan oleh model.

Untuk melakukannya dapat kita gunakan dengan bantuan visual dari fungsi plot(nama_model, which = 1).

kondisi yang diharapkan dari hasi visual adalah nilai residual “bounce randomly” di sekitar nilai 0.

plot(model2, # model yg akan diujikan
     which = 1) # residual vs fitted

💡 Insight:

Berdasarkan hasil visualisasi scatter plot residual vs fitted values diatas dapat kita ketahui bahwa residual menyebar cukup acak di sekitar garis nol.

2. Normalitas

Untuk melakukan pengujian normalitas sisaan dapat kita lakukan menggunakan fungsi shapiro.test() dari package stats dengan hipotesis yang diuji adalah sebagai berikut:

H0 : Sisaan menyebar normal
H1 : Sisaan tidak menyebar normal

dengan kriteria pengujian H0 ditolak jika P-value < α. Nilai α yang digunakan sebesar 5%.

hasil yang diharapkan adalah menerima H0 (p-value > 0)

shapiro.test(model2$residuals)
#> 
#>  Shapiro-Wilk normality test
#> 
#> data:  model2$residuals
#> W = 0.89031, p-value < 0.00000000000000022

💡 Insight:

Berdasarkan hasil pengujian shapiro test diatas dapat kita ketahui bahwa sisaan tidak menyebar secara normal. Artinya asumsi normalitas tidak terpenuhi.

3. Heteroskedastisitas

Untuk melakukan pengujian heteroskedastisitas varians dapat kita lakukan menggunakan fungsi bptest() dari package lmtest dengan hipotesis yang diuji adalah sebagai berikut.

H0 : Sisaan memiliki ragam homogen
H1 : Sisaan tidak memiliki ragam homogen

dengan kriteria pengujian H0 ditolak jika P-value < α. Nilai α yang digunakan sebesar 5%.

hasil yang diharapkan adalah menerima H0 (p-value > 0)

bptest(model2)
#> 
#>  studentized Breusch-Pagan test
#> 
#> data:  model2
#> BP = 125.08, df = 5, p-value < 0.00000000000000022

💡 Insight:

Berdasarkan hasil pengujian breusch-pagan test diatas dapat kita ketahui bahwa sisaan tidak memiliki ragam yang homogen. Artinya asumsi heteroskedastisitas tidak terpenuhi.


3.3 Model Improvement

Dari hasil pengujian asumsi yang telah dilakukan 2 dari 4 asumsi yang terpenuhi, yakni tidak terjadi multikolinieritas dan linieritas. Sedangkan untuk asumsi normalitas dan heteroskedastisitas.

Salah satu metode yang dapat dilakukan agar dapat memenuhi asumsi normalitas dan heteroskedastisitas adalah dengan melakukan transformasi data untuk variabel prediktor dan respon, dan salah satu transformasi yang dapat dilakukan adalah transformasi logaritmik.

Dengan mempertimbangkan hasil uji signifikansi yang diperoleh dari summary model2 yang telah dibuat, variabel prediktor Length memiliki nilai p-value yang lebih besar diantara variabel prediktor lainnya. Maka untuk variabel prediktor Length dan variabel target Age.

3.3.1 Model Tuning

model_tuning <- lm(formula = log(Age) ~ Sex + Height + log(Length) + Weight, 
                 data = crab_train) 
summary(model_tuning)
#> 
#> Call:
#> lm(formula = log(Age) ~ Sex + Height + log(Length) + Weight, 
#>     data = crab_train)
#> 
#> Residuals:
#>      Min       1Q   Median       3Q      Max 
#> -0.68302 -0.14837 -0.03188  0.11068  0.87638 
#> 
#> Coefficients:
#>               Estimate Std. Error t value             Pr(>|t|)    
#> (Intercept)  1.6571264  0.0264406  62.673 < 0.0000000000000002 ***
#> SexF         0.1161690  0.0120586   9.634 < 0.0000000000000002 ***
#> SexM         0.1075346  0.0113495   9.475 < 0.0000000000000002 ***
#> Height       1.5324185  0.1092856  14.022 < 0.0000000000000002 ***
#> log(Length)  0.4319887  0.0343462  12.577 < 0.0000000000000002 ***
#> Weight      -0.0052656  0.0007055  -7.464     0.00000000000011 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 0.2195 on 2914 degrees of freedom
#> Multiple R-squared:  0.5058, Adjusted R-squared:  0.505 
#> F-statistic: 596.5 on 5 and 2914 DF,  p-value: < 0.00000000000000022

💡 Insight:

Berdasarkan hasil summary model_tuning diatas terlihat kini seluruh prediktor sudah signifikan yang ditandai dengan adanya tanda *** dan nilai p-value < 0,05. dan terjadi peningkatan pada nilai Adjusted R-squared menjad 0.505.

3.3.2 Model Performance

Dikarenakan model_tuning yang dibuat dengan target dan prediktor yang sudah ditransformasi menajdi logaritmik, maka untuk hasil prediksi perlu dikembalikan kedalam nilai asli terlebih dahulu dengan menggunakan fungsi exp().

pred_train2 <- exp(model_tuning$fitted.values)
pred_test2 <- exp(predict(model_tuning,crab_test))

Eval_tuning <- data.frame(Data = c("Data Train", "Data Test"),
                   MAPE_model2 = c(MAPE(pred_train,crab_train$Age)*100, 
                                   MAPE(pred_test, crab_test$Age)*100),
                   MAPE_Tuning = c(MAPE(pred_train2,crab_train$Age)*100, 
                                   MAPE(pred_test2, crab_test$Age)*100))
Eval_tuning

💡 Insight:

Berdasarkan hasil evaluasi model_tuning diatas terlihat adanya perubahan performa baik pada data train maupun data test setelah dilakukan tuning model. Namun melihat dari nilai MAPE yang tidak lebih dari 25%, maka model dirasa masih cukup baik dalam memprediksi data baru.


3.3.3 Assumption Checking

1. Linearitas

plot(model_tuning, which = 1)

💡 Insight:

Berdasarkan hasil visualisasi scatter plot residual vs fitted values diatas dapat kita ketahui bahwa residual menyebar cukup acak di sekitar garis nol.

2. Normalitas

Hipotesis yang diujikan:

H0 : Sisaan menyebar normal
H1 : Sisaan tidak menyebar normal

dengan kriteria pengujian H0 ditolak jika P-value < α. Nilai α yang digunakan sebesar 5%.

hasil yang diharapkan adalah menerima H0 (p-value > 0)

shapiro.test(model_tuning$residuals)
#> 
#>  Shapiro-Wilk normality test
#> 
#> data:  model_tuning$residuals
#> W = 0.96747, p-value < 0.00000000000000022

💡 Insight:

Berdasarkan hasil pengujian shapiro test diatas dapat kita ketahui bahwa sisaan tidak menyebar secara normal. Artinya asumsi normalitas masih tidak terpenuhi.

3. Heteroskedastisitas

Hipotesis yang diujikan:

H0 : Sisaan memiliki ragam homogen
H1 : Sisaan tidak memiliki ragam homogen

dengan kriteria pengujian H0 ditolak jika P-value < α. Nilai α yang digunakan sebesar 5%.

hasil yang diharapkan adalah menerima H0 (p-value > 0)

bptest(model_tuning)
#> 
#>  studentized Breusch-Pagan test
#> 
#> data:  model_tuning
#> BP = 65.428, df = 5, p-value = 0.0000000000009135

💡 Insight:

Berdasarkan hasil pengujian breusch-pagan test diatas dapat kita ketahui bahwa sisaan tidak memiliki ragam yang homogen. Artinya asumsi heteroskedastisitas masih tidak terpenuhi.

Model regresi ketat akan asumsi,namun pada kondisi di lapangan untuk memenuhi keempat asumsi ini sangat sulit terpenuhi. oleh karenanya, sebagai syarat utama menggunakan model regresi minimal asumsi yang harus terpenuhinya adalah asumsi linieritas dan no multikolinieritas. Namun apabila ingin dioptimalkan agar model memenuhi asumsi normalitas dan heteroskedastisitasnya maka metode lain yang dapat dilakukan adalah dengan memberikan penanganan data outlier dan atau penambahan data.


3.4 Model Interpretation

Salah satu keunggulan model regresi adalah mudah untuk diinterpretasikan. Dikarenakan hasil transformasi tidak menjadikan model menjadi lebih baik, maka model final yang akan digunakan adalah model2 yang dibuat menggunakan data asli.

summary(model2)
#> 
#> Call:
#> lm(formula = Age ~ Sex + Height + Length + Weight, data = crab_train)
#> 
#> Residuals:
#>     Min      1Q  Median      3Q     Max 
#> -6.0775 -1.5807 -0.5166  0.8538 14.9977 
#> 
#> Coefficients:
#>              Estimate Std. Error t value             Pr(>|t|)    
#> (Intercept)  2.573929   0.367400   7.006 0.000000000003037826 ***
#> SexF         1.109700   0.136922   8.105 0.000000000000000771 ***
#> SexM         0.960195   0.128845   7.452 0.000000000000120187 ***
#> Height      18.181021   1.205283  15.084 < 0.0000000000000002 ***
#> Length       0.591763   0.462461   1.280               0.2008    
#> Weight      -0.019679   0.009597  -2.051               0.0404 *  
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 2.493 on 2914 degrees of freedom
#> Multiple R-squared:  0.3803, Adjusted R-squared:  0.3792 
#> F-statistic: 357.6 on 5 and 2914 DF,  p-value: < 0.00000000000000022

💡 Insight:

Berdasarkan pembuatan model regresi berganda sebelumnya diperoleh persamaan regresi sebagai berikut:

\[\hat{Age} = 2.573929 + 1.109700*SexF + 0.960195*SexM + 18.181021*Height + 0.591763*Length - 0.019679*Weight\]

  1. Interpretasi coefficient untuk prediktor kategorik: Sex
    • Sex = I : menjadi basis
    • Sex = F : 1.109700, Usia kepiting lebih besar 1.109700 bulan apabila berjeniskelamin betina [SexF = 1 & Sex M = 0] dibandingkan dengan kepiting yang belum diketahui jenis kelaminnya [SexF = 0 & SexM = 0] dengan catatan variabel prediktor lainnya bernilai tetap
    • Sex = M : 0.960195, Usia kepiting lebih besar 0.960195 bulan apabila berjeniskelamin jantan [SexF = 0 & Sex M = 1] dibandingkan dengan kepiting yang belum diketahui jenis kelaminnya [SexF = 0 & SexM = 0] dengan catatan variabel prediktor lainnya bernilai tetap
  2. Interpretasi coefficient untuk prediktor numerik:
    • Height : 18.181021, Usia kepiting akan bertambah sebesar 18.181021 bulan untuk setiap pertambahan tinggi sebesar 1 kaki, dengan catatan variabel prediktor lainnya bernilai tetap
    • Length : 0.591763, Usia kepiting akan bertambah sebesar 0.591763 bulan untuk setiap pertambahan panjang sebesar 1 kaki, dengan catatan variabel prediktor lainnya bernilai tetap
    • Weight : -0.019679, Usia kepiting akan berkurang sebesar 0.019679 bulan untuk setiap pertambahan berat sebesar 1 ons, dengan catatan variabel prediktor lainnya bernilai tetap

4 Conclusion

Dari serangkaian proses analisis yang telah dilakukan dapat diperoleh kesimpulan bahwa kepiting yang belum teridentifikasi jenis kelaminnya cenderung berusia kurang dari 9 bulan, kepiting jantan cenderung memiliki dimensi dan volume yang lebih besar dibandingkan kepiting betina dan faktor-faktor yang signifikan dapat digunakan sebagai acuan prediksi usia kepiting oleh peternak kepiting adalah jenis kelamin kepiting, tinggi/ketebalan kepiting, dan berat kepiting.